#include "item.h"

#include "list.h"
#include "source.h"

#include "namespace.h"
#include "uniquename.h"

#include <QStringList>

Item::Item(
    NameSpace *nameSpace
,   const QString &name)
:   QObject()
,   m_nameSpace(new NameSpace())
,   m_ignored(false)
,   m_name(NULL)
,   m_quantity(1)
{
    m_name = new UniqueName(name.toStdString());
    m_name->setNameSpace(nameSpace);
}

Item::~Item()
{
    foreach(Source *source, m_sources)
        removeSource(source);

    delete m_name;
    delete m_nameSpace;
}

const Item::t_sources Item::sources() const
{
    return m_sources;
}

NameSpace *Item::nameSpace()
{
    return m_nameSpace;
}

void Item::setName(const QString &name)
{
    if(name == this->name())
        return;

    std::string n(name.toStdString());
    m_name->setName(n);

    emit nameChanged(this->name());
    emit modified();
}

const QString Item::name() const
{
    return QString::fromStdString(m_name->name());
}

void Item::setQuantity(const uint quantity)
{
    if(quantity == m_quantity)
        return;

    m_quantity = quantity;

    emit quantityChanged(m_quantity);
    emit modified();
}

const uint Item::quantity() const
{
    return m_quantity;
}

void Item::setIgnored(const bool ignored)
{
    if(ignored == m_ignored)
        return;

    m_ignored = ignored;

    emit ignoreStateChanged(m_ignored);
    emit modified();
}

const bool Item::ignored() const
{
    return m_ignored;
}

Source *Item::source(const QString &name)
{
    foreach(Source *source, m_sources)
        if(source->name() == name)
        return source;

    return NULL;
}

void Item::addSource(Source *source)
{
    m_sources.append(source);

    connect(source, SIGNAL(modified()), this, SIGNAL(modified()));

    connect(source, SIGNAL(updated(bool))
        , this, SLOT(source_updated(bool)));
    connect(source, SIGNAL(canceled())
        , this, SLOT(source_canceled()));

    emit sourceAdded(source);
    emit modified();
}

void Item::removeSource(Source *source)
{
    if(!source)
        return;

    m_sources.remove(m_sources.indexOf(source));

    emit sourceRemoved(source);
    emit modified();

    delete source;
}




void Item::update()
{
    if(isUpdating())
        return;

    m_succeeded = 0;
    m_failed = 0;

    foreach(Source *source, m_sources)
        source->update();
}

void Item::cancel()
{
    if(!isUpdating())
        return;

    foreach(Source *source, m_sources)
        source->cancel();
}

void Item::source_updated(bool succeeded)
{
    if(succeeded)
        ++m_succeeded;
    else
        ++m_failed;

    if(isUpdating())
        return;

    emit updated(m_succeeded, m_failed);
}

void Item::source_canceled()
{
    if(isUpdating())
        return;

    emit updated(m_succeeded, m_failed);
}

const bool Item::isUpdating() const
{
    foreach(Source *source, m_sources)
        if(source->isUpdating())
            return true;

    return false;
}
